package com.nsl.my_youlai.bbu2.model.bo.bbu;

import com.nsl.my_youlai.bbu2.enums.BbuModelEnum;
import com.nsl.my_youlai.bbu2.enums.BoardTypeEnum;
import com.nsl.my_youlai.bbu2.enums.NetGenerationEnum;
import com.nsl.my_youlai.bbu2.enums.VendorEnum2;
import com.nsl.my_youlai.bbu2.model.bo.ApparatusRoomBo;
import com.nsl.my_youlai.bbu2.model.bo.bbu.rules.BbuBaseSlotRules;
import com.nsl.my_youlai.mystar.NslUtilList;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
@Data
abstract  public class Bbu2 {

    private int excelRowIndex;

    protected Integer id;

    protected VendorEnum2 vendor;

    protected Integer nodeId;

    protected BbuModelEnum bbuModelEnum;

    private String ApparatusRoomId;

    private BbuBaseSlotRules slotRules;

    private ApparatusRoomBo apparatusRoomBo;

    private int maxBaseBoard=4;

    //4G,5G
//    protected NetGenerationEnum netGenerationFromBbuModel;

    public NetGenerationEnum getNetGenerationFromBbuModel(){
        return bbuModelEnum.getNetGenerationEnum();
    }


    protected List<BbuFrame> bbuFrameList=new ArrayList<>();

    protected List<BbuFun> bbuFunList=new ArrayList<>();

    protected List<Integer> soltIndexList=new ArrayList<>();
    protected Map<Integer, BbuSlot2> slotMap=new HashMap<>();



    public int getFunCounter(){
        return bbuFunList.size();
    }

    public int getFrameCounter(){
        return bbuFrameList.size();
    }

    public int getBaseBoardCounter(){
        return getBoardCounter(BoardTypeEnum.BASE_BAND_BOARD);

    }

    public int getControlBoardCounter(){
        return getBoardCounter(BoardTypeEnum.CONTROL_BOARD);
    }

    public int getPowerBoardCounter(){
        return getBoardCounter(BoardTypeEnum.POWER_BOARD);
    }

    //4base_1main_1power_1frame_1fun
    public String getBoardStringIndex(){
        List<Integer> list=new ArrayList<>();
        list.add(getBaseBoardCounter());
        list.add(getControlBoardCounter());
        list.add(getPowerBoardCounter());
        list.add(getFrameCounter());
        list.add(getFunCounter());
        return NslUtilList.list2String(list);
    }

//        protected Integer frameCounter=0;
//    protected Integer baseBoardCounter=0;
//
//    protected Integer controlBoardCounter =0;
//
//    protected Integer powerBoardCounter=0;
//
//    protected Integer funCounter=0;



    private List<String> errorMsgList =new ArrayList<>();

    private List<String> warnMsgList=new ArrayList<>();

//    protected List<Integer> bbuSlotRuleIndexList;
//
//    protected  Map<Integer,BbuSlotRule> bbuSlotRuleMap;



//    public Integer getIntIndex(){
//        return frameCounter*10000+funCounter*1000+powerBoardCounter*100+ controlBoardCounter *10+baseBoardCounter;
//    }
//
//    public void setIntIndex(Integer intIndex){
//        this.frameCounter=intIndex/10000;
//        this.funCounter=(intIndex%10000)/1000;
//        this.powerBoardCounter=(intIndex%1000)/100;
//        this.controlBoardCounter =(intIndex%100)/10;
//        this.baseBoardCounter=intIndex%10;
//    }


    public Bbu2() {
    }

    public Bbu2(int excelRowIndex, VendorEnum2 vendor, BbuModelEnum bbuModelEnum, Integer nodeId,String baseBoardSlots,String controlBoardSlots,String powerBoardSlots,String stringIndex){
        this(excelRowIndex,vendor,bbuModelEnum,nodeId,baseBoardSlots,controlBoardSlots,powerBoardSlots);
        List<Integer> integerList=NslUtilList.string2IntList(stringIndex,"_");


        List<BbuBoard2> baseBoardList=createBoardList(BoardTypeEnum.BASE_BAND_BOARD,nodeId,integerList.get(0));
        addBoardsToSlots(baseBoardSlots,BoardTypeEnum.BASE_BAND_BOARD,baseBoardList);

        List<BbuBoard2> controlBoardList=createBoardList(BoardTypeEnum.CONTROL_BOARD,nodeId,integerList.get(1));
        addBoardsToSlots(controlBoardSlots,BoardTypeEnum.CONTROL_BOARD,controlBoardList);

        List<BbuBoard2> powerBoardList=createBoardList(BoardTypeEnum.POWER_BOARD,nodeId,integerList.get(2));
        addBoardsToSlots(powerBoardSlots,BoardTypeEnum.POWER_BOARD,powerBoardList);

        for (Integer i = 0; i < integerList.get(3); i++) {
            BbuFrame bbuFrame=new BbuFrame();
            bbuFrame.setNodeId(nodeId);
            bbuFrameList.add(bbuFrame);
        }

        for (Integer i = 0; i < integerList.get(4); i++) {
            BbuFun bbuFun=new BbuFun();
            bbuFun.setNodeId(nodeId);
            bbuFunList.add(bbuFun);
        }

    }

    public Bbu2(int excelRowIndex, VendorEnum2 vendor, BbuModelEnum bbuModelEnum, Integer nodeId ,String baseBoardSlots,String controlBoardSlots,String powerBoardSlots) {
        this.excelRowIndex = excelRowIndex;
        this.vendor = vendor;
        this.nodeId = nodeId;
        this.bbuModelEnum = bbuModelEnum;

        List<Integer> baseList=NslUtilList.string2IntList(baseBoardSlots);
        List<Integer> controlList=NslUtilList.string2IntList(controlBoardSlots);
        List<Integer> powerList=NslUtilList.string2IntList(powerBoardSlots);
        Set<Integer> slotSet=new HashSet<>();
        slotSet.addAll(baseList);
        slotSet.addAll(controlList);
        slotSet.addAll(powerList);

        for (Integer integer : slotSet) {
            BbuSlot2 bbuSlot=new BbuSlot2();
            bbuSlot.setNodeId(nodeId);
            bbuSlot.setSlotIndex(integer);
            soltIndexList.add(integer);
            slotMap.put(integer,bbuSlot);
        }
    }

//    public Bbu2(Integer frameCounter, Integer funCounter, Integer powerBoardCounter, Integer controlBoardCounter, Integer baseBoardCounter) {
//        this();
//        this.frameCounter = frameCounter;
//        this.baseBoardCounter = baseBoardCounter;
//        this.controlBoardCounter = controlBoardCounter;
//        this.powerBoardCounter = powerBoardCounter;
//        this.funCounter = funCounter;
//    }
//
//    public Bbu2(Integer frameCounter, Integer funCounter, Integer powerBoardCounter, Integer controlBoardCounter, Integer baseBoardCounter, Integer nodeId) {
//        this(frameCounter,funCounter,powerBoardCounter, controlBoardCounter,baseBoardCounter);
//        this.nodeId=nodeId;
//    }

     public abstract  void bbuCheck();


    //根据intIndex， 从source bbu  删除boards,在target，即this bbu 中，增加 boards
//    abstract public void integrateBoardByIntIndex(Bbu2 sourceBbu,int intIndex);

    public List<BbuBoard2> removeBoardsFromSlots(Bbu2 bbu, String slots, BoardTypeEnum boardTypeEnum, int boardCounter){
        List<BbuBoard2> removedBoardList=new ArrayList<>();
        if(boardCounter<=0) return removedBoardList;
        List<Integer> slotIndexList= NslUtilList.string2IntList(slots);
        Map<Integer, BbuSlot2> slotMap=bbu.getSlotMap();

        for (Integer integer : slotIndexList) {
            if(boardCounter==0){
                return removedBoardList;
            }
            BbuSlot2 slot=slotMap.get(integer);

            if(slot.getBbuBoardList().size()>0){
                //需排除交换板，因为交换板和基带板，可以配置序号一样的插槽，但只能插一个
                //目前考虑是： 交换板，全部去除掉
                BoardTypeEnum slotBoardType=slot.getBbuBoardList().get(0).getBoardTypeEnum();
                if( slotBoardType != BoardTypeEnum.SWITCH_BOARD && slotBoardType!=boardTypeEnum){
                    log.info("slot.getBbuBoardList().get(0) = {}",slot.getBbuBoardList().get(0).getExcelRowIndex());
                    log.info("boardTypeEnum = {}",boardTypeEnum);
                    throw new RuntimeException("slot存在的board type，同拟删除的 board type 不一致");
                }
                List<BbuBoard2> slotBoardList=slot.getBbuBoardList();

                //需要 boardType 一致，因为交换板和基带板可以放置在同序号插槽
                if(boardTypeEnum==slotBoardType){
                    if(slot.getBbuBoardList().size()>boardCounter){
                        removedBoardList.addAll(slotBoardList.subList(0,boardCounter));
                        slot.setBbuBoardList(slotBoardList.subList(boardCounter,slotBoardList.size()));
                    }else{
                        removedBoardList.addAll(slotBoardList);
                        slot.setBbuBoardList(new ArrayList<>());
                        boardCounter=boardCounter-slotBoardList.size();
                    }
                }

            }
        }
        return removedBoardList;
    }


    abstract  public void integrateBoards(Bbu2 sourceBbu, String cutoffsStringIndex);

    public void addBoardsToSlots(String slots, BoardTypeEnum boardTypeEnum, List<BbuBoard2> boardList){
        if(boardList.size()==0){
            return ;
        }
        List<Integer> slotIndexList= NslUtilList.string2IntList(slots);
        int addIndex=0;

        for (Integer integer : slotIndexList) {
            BbuSlot2 bbuSlot=slotMap.get(integer);
            if(bbuSlot.getBbuBoardList().size()==0){
                bbuSlot.getBbuBoardList().add(boardList.get(addIndex));
                addIndex++;
                if(addIndex==boardList.size()){
                    return;
                }
            }
        }
        if(addIndex!=boardList.size()){
            throw new RuntimeException("拟插入的板卡，已无空余插槽可以插入");
        }
    }

    private int getBoardCounter(BoardTypeEnum boardTypeEnum){
        int counter=0;
        for (Map.Entry<Integer, BbuSlot2> integerBbuSlot2Entry : slotMap.entrySet()) {
            BbuSlot2 bbuSlot=integerBbuSlot2Entry.getValue();
            for (BbuBoard2 bbuBoard : bbuSlot.getBbuBoardList()) {
                if(bbuBoard.getBoardTypeEnum()==boardTypeEnum){
                    counter++;
                }

            }
        }
        return counter;
    }


    public void integrateBoards(Bbu2 sourceBbu, String cutoffsStringIndex,String baseBoardSlots, String controlBoardSlots,String powerBoardSlots) {
        List<Integer> integerList= NslUtilList.string2IntList(cutoffsStringIndex,"_");

        Integer frameCounter=integerList.get(3);
        Integer funCounter=integerList.get(4);
        Integer powerBoardCounter=integerList.get(2);
        Integer controlBoardCounter =integerList.get(1);
        Integer baseBoardCounter=integerList.get(0);

        //处理 frameCounter
        if(frameCounter>0){
            List<BbuFrame> sourceFrameList=sourceBbu.getBbuFrameList();
            List<BbuFrame> cutFrameList=sourceFrameList.subList(0,frameCounter);
            bbuFrameList.addAll(cutFrameList);
            sourceBbu.setBbuFrameList(sourceFrameList.subList(frameCounter,sourceFrameList.size()));
        }
        if(funCounter>0){
            List<BbuFun> sourceFunList=sourceBbu.getBbuFunList();
            List<BbuFun> cutFunList=sourceFunList.subList(0,funCounter);
            bbuFunList.addAll(cutFunList);
            sourceBbu.setBbuFunList(sourceFunList.subList(funCounter,sourceFunList.size()));
        }


        if(baseBoardCounter>0){
            List<BbuBoard2> removedBoards= removeBoardsFromSlots(sourceBbu,baseBoardSlots, BoardTypeEnum.BASE_BAND_BOARD,baseBoardCounter);
            addBoardsToSlots(baseBoardSlots,BoardTypeEnum.BASE_BAND_BOARD,removedBoards);
        }
        if(controlBoardCounter>0){
            List<BbuBoard2> removedBoards= removeBoardsFromSlots(sourceBbu,controlBoardSlots,BoardTypeEnum.CONTROL_BOARD,controlBoardCounter);
            addBoardsToSlots(controlBoardSlots,BoardTypeEnum.CONTROL_BOARD,removedBoards);
        }
        if(powerBoardCounter>0){
            List<BbuBoard2> removedBoards= removeBoardsFromSlots(sourceBbu,powerBoardSlots,BoardTypeEnum.POWER_BOARD,powerBoardCounter);
            addBoardsToSlots(powerBoardSlots,BoardTypeEnum.POWER_BOARD,removedBoards);
        }
    }

    private List<BbuBoard2> createBoardList(BoardTypeEnum boardTypeEnum,Integer nodeId,int counter){
        List<BbuBoard2> list=new ArrayList<>();
        for (int i = 0; i < counter; i++) {
            BbuBoard2 bbuBoard=new BbuBoard2();
            bbuBoard.setNodeId(nodeId);
            bbuBoard.setBoardTypeEnum(boardTypeEnum);
            list.add(bbuBoard);
        }
        log.info("list.size() = {}",list.size());
        return list;
    }


    @Override
    public boolean equals(Object other){

        Bbu2 bbu2= (Bbu2) other;
        if(other==null){
            return false;
        }
        if(bbu2.getNodeId()==null){
            return false;
        }
        return nodeId.equals(bbu2.nodeId);
    }



    @Override
    public String toString() {
        return "BBu2{" +
                "vendor=" + vendor +
                ", bbuModelName='" + bbuModelEnum + '\'' +
                ", nodeId=" + nodeId +
                ", frameCounter=" + getFrameCounter() +
                ", funCounter=" + getFunCounter() +
                ", powerBoardCounter=" + getPowerBoardCounter() +
                ", mainBoardCounter=" + getControlBoardCounter() +
                ", baseBoardCounter=" + getBaseBoardCounter() +
                '}';
    }
}
